#include "SerialScreen.h"
#include "Gateway_Node.h"

#include "common_def.h"
#include "soc_osal.h"
#include "app_init.h"
#include "osal_event.h"

#define CODE_LOG "[SerialScreen]"

// 串口屏通信参数
static uint8_t g_uart_gui_rx_buff[CONFIG_SERIAL_SCREEN_RX_BUF_SIZE] = {0};
static uart_buffer_config_t g_uart_gui_buffer_config = {
    .rx_buffer = g_uart_gui_rx_buff,
    .rx_buffer_size = CONFIG_SERIAL_SCREEN_RX_BUF_SIZE,
};

// 串口屏基本指令(第[0]位为指令长度)
static uint8_t const SerialScreen_Command[][64] = {
    {0x0A, 0xEE, 0x07, 0x35, 0x5A, 0x53, 0xA5, 0xFF, 0xFC, 0xFF, 0xFF}, // 0, 串口屏设备重启
    {0x06, 0xEE, 0x04, 0xFF, 0xFC, 0xFF, 0xFF},                         // 1, 串口屏设备握手
    {0x09, 0xEE, 0xB1, 0x00, 0x00, 0x01, 0xFF, 0xFC, 0xFF, 0xFF},       // 2, 切换到主界面
};

// 串口屏电机速度选项组
static uint8_t const SerialScreen_MotorSpeedOption[] = {40, 50, 60, 70, 80, 90, 100};

// 串口屏GUI的UART接收回调函数
static void GUI_uart_rx_callback(const void *buffer, uint16_t length, bool error)
{
    static uint8_t SystemTime_hour = 0, SystemTime_minute = 0, SystemTime_second = 0; // 定义系统时间修改存储变量

    if (buffer == NULL || length == 0)
    {
        return;
    }

    // 打开接收的数据
    osal_printk("%s uart_rx: ", CODE_LOG);
    for (uint16_t i = 0; i < length; i++)
    {
        osal_printk("%02X ", ((uint8_t *)buffer)[i]);
    }
    osal_printk("\n");

    // 验证是否串口屏数据
    if (((uint8_t *)buffer)[0] != 0xEE || ((uint8_t *)buffer)[length - 4] != 0xFF || ((uint8_t *)buffer)[length - 3] != 0xFC || ((uint8_t *)buffer)[length - 2] != 0xFF || ((uint8_t *)buffer)[length - 1] != 0xFF)
    {
        osal_printk("%s SerialScreen data error!\n", CODE_LOG);

        return;
    }

    // 接收到设备启动信息，切换到主界面
    if (((uint8_t *)buffer)[1] == 0x07)
    {
        SerialScreen_SendCommand(2);
    }
    // 接收到控件信息上报
    else if (((uint8_t *)buffer)[1] == 0xB1 && ((uint8_t *)buffer)[2] == 0x11)
    {
        // 电机速度控制    判断界面ID 0x0002 和控件ID 0x0005
        if (((uint8_t *)buffer)[3] == 0x00 && ((uint8_t *)buffer)[4] == 0x02 && ((uint8_t *)buffer)[5] == 0x00 && ((uint8_t *)buffer)[6] == 0x05)
        {
            // osal_printk("%s SerialScreen_MotorSpeedOption[%d]: %d\n", CODE_LOG, ((uint8_t *)buffer)[8], SerialScreen_MotorSpeedOption[((uint8_t *)buffer)[8]]);
            g_system_data.MotprSpeed = SerialScreen_MotorSpeedOption[((uint8_t *)buffer)[8]]; // 设置系统电机速度
        }

        // 电机前进控制    判断界面ID 0x0002 和控件ID 0x0006
        else if (((uint8_t *)buffer)[3] == 0x00 && ((uint8_t *)buffer)[4] == 0x02 && ((uint8_t *)buffer)[5] == 0x00 && ((uint8_t *)buffer)[6] == 0x06)
        {
            if (((uint8_t *)buffer)[9] == 0x01) // 电机前进
            {
                osal_event_write(&g_EventHandle_SystemEvent, SYSTEM_EVENT_MOTOR_ADVANCE);
            }
            else if (((uint8_t *)buffer)[9] == 0x00) // 电机停止
            {
                osal_event_write(&g_EventHandle_SystemEvent, SYSTEM_EVENT_MOTOR_STOP);
            }
        }

        // 电机右转控制    判断界面ID 0x0002 和控件ID 0x0007
        else if (((uint8_t *)buffer)[3] == 0x00 && ((uint8_t *)buffer)[4] == 0x02 && ((uint8_t *)buffer)[5] == 0x00 && ((uint8_t *)buffer)[6] == 0x07)
        {
            if (((uint8_t *)buffer)[9] == 0x01) // 电机右转
            {
                osal_event_write(&g_EventHandle_SystemEvent, SYSTEM_EVENT_MOTOR_RIGHT);
            }
            else if (((uint8_t *)buffer)[9] == 0x00) // 电机停止
            {
                osal_event_write(&g_EventHandle_SystemEvent, SYSTEM_EVENT_MOTOR_STOP);
            }
        }

        // 电机后退控制    判断界面ID 0x0002 和控件ID 0x0008
        else if (((uint8_t *)buffer)[3] == 0x00 && ((uint8_t *)buffer)[4] == 0x02 && ((uint8_t *)buffer)[5] == 0x00 && ((uint8_t *)buffer)[6] == 0x08)
        {
            if (((uint8_t *)buffer)[9] == 0x01) // 电机后退
            {
                osal_event_write(&g_EventHandle_SystemEvent, SYSTEM_EVENT_MOTOR_BACK);
            }
            else if (((uint8_t *)buffer)[9] == 0x00) // 电机停止
            {
                osal_event_write(&g_EventHandle_SystemEvent, SYSTEM_EVENT_MOTOR_STOP);
            }
        }

        // 电机左转控制    判断界面ID 0x0002 和控件ID 0x0009
        else if (((uint8_t *)buffer)[3] == 0x00 && ((uint8_t *)buffer)[4] == 0x02 && ((uint8_t *)buffer)[5] == 0x00 && ((uint8_t *)buffer)[6] == 0x09)
        {
            if (((uint8_t *)buffer)[9] == 0x01) // 电机左转
            {
                osal_event_write(&g_EventHandle_SystemEvent, SYSTEM_EVENT_MOTOR_LEFT);
            }
            else if (((uint8_t *)buffer)[9] == 0x00) // 电机停止
            {
                osal_event_write(&g_EventHandle_SystemEvent, SYSTEM_EVENT_MOTOR_STOP);
            }
        }
    }
}

/**
 * @brief  串口屏初始化
 * @param  None
 * @retval ERRCODE_SUCC 成功。
 * @retval Other        失败，参考 @ref errcode_t 。
 */
errcode_t SerialScreen_Init(void)
{
    // 初始化串口屏通信
    if (bsp_uart_init(CONFIG_SERIAL_SCREEN_UART_ID, CONFIG_SERIAL_SCREEN_BAUDRATE, &g_uart_gui_buffer_config) != ERRCODE_SUCC)
    {
        osal_printk("%s SerialScreen_Init uart init fail!\n", CODE_LOG);
        return ERRCODE_UART_NOT_INIT;
    }
    if (bsp_uart_register_rx(CONFIG_SERIAL_SCREEN_UART_ID, GUI_uart_rx_callback) != ERRCODE_SUCC) // 注册串口接收回调函数
    {
        osal_printk("%s SerialScreen_Init uart register rx fail!\n", CODE_LOG);
        return ERRCODE_UART_NOT_INIT;
    }

    // 初始化串口屏电源控制GPIO
    errcode_t ret = ERRCODE_SUCC;
    if (CONFIG_SERIAL_SCREEN_POWER_PIN == GPIO_04)
    {
        ret = uapi_pin_set_mode(CONFIG_SERIAL_SCREEN_POWER_PIN, PIN_MODE_2); // 设置引脚模式
    }
    else if (CONFIG_SERIAL_SCREEN_POWER_PIN == GPIO_05)
    {
        ret = uapi_pin_set_mode(CONFIG_SERIAL_SCREEN_POWER_PIN, PIN_MODE_4); // 设置引脚模式
    }
    else
    {
        ret = uapi_pin_set_mode(CONFIG_SERIAL_SCREEN_POWER_PIN, PIN_MODE_0); // 设置引脚模式
    }
    if (ret != ERRCODE_SUCC)
    {
        osal_printk("%s: set SerialScreen_Power pin mode failed, ret = %d\n", CODE_LOG, ret);
        return ret;
    }
    ret = uapi_gpio_set_dir(CONFIG_SERIAL_SCREEN_POWER_PIN, GPIO_DIRECTION_OUTPUT); // 设置引脚方向
    if (ret != ERRCODE_SUCC)
    {
        osal_printk("%s: set SerialScreen_Power pin direction failed, ret = %d\n", CODE_LOG, ret);
        return ret;
    }
    ret = uapi_gpio_set_val(CONFIG_SERIAL_SCREEN_POWER_PIN, GPIO_LEVEL_HIGH); // 设置引脚值
    if (ret != ERRCODE_SUCC)
    {
        osal_printk("%s: set SerialScreen_Power pin value failed, ret = %d\n", CODE_LOG, ret);
        return ret;
    }

    return ERRCODE_SUCC;
}

/**
 * @brief  串口屏发送控制指令
 * @param  [in] cmd_id  命令ID
 * @retval ERRCODE_SUCC 成功。
 * @retval Other        失败，参考 @ref errcode_t 。
 */
errcode_t SerialScreen_SendCommand(uint8_t cmd_id)
{
    uint16_t cmd_id_max = sizeof(SerialScreen_Command) / sizeof(SerialScreen_Command[0]);
    osal_printk("%s cmd_id_max = %d\n", CODE_LOG, cmd_id_max);
    if (cmd_id >= cmd_id_max)
    {
        osal_printk("%s SerialScreen_SendCommand cmd_id is out of instruction table range.\n", CODE_LOG);
        return ERRCODE_INVALID_PARAM;
    }

    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, SerialScreen_Command[cmd_id] + 1, SerialScreen_Command[cmd_id][0]);

    return ERRCODE_SUCC;
}

/**
 * @brief  串口屏硬件复位
 * @param  None
 * @retval None
 * */
void SerialScreen_Reset(void)
{
    // 电源引脚拉低后重启
    uapi_gpio_set_val(CONFIG_SERIAL_SCREEN_POWER_PIN, GPIO_LEVEL_LOW); // 设置引脚值
    osal_msleep(100);
    uapi_gpio_set_val(CONFIG_SERIAL_SCREEN_POWER_PIN, GPIO_LEVEL_HIGH); // 设置引脚值
}

/**
 * @brief  串口屏上报网络状态
 * @param  [in] state 网络状态 参考 @ref network_state_t 。
 * @retval None
 * */
void SerialScreen_ReportNetworkState(network_state_t state)
{
    // 上报基本指令
    uint8_t cmd[12] = {0xEE, 0xB1, 0x23, 0x00, 0x01, 0x00, 0x02, 0x00, 0xFF, 0xFC, 0xFF, 0xFF};

    // 修改网络状态值
    cmd[7] = state;

    // 对所有界面上报网络状态数据
    for (uint8_t i = 0; i <= SERIAL_SCREEN_ID_MAX; i++)
    {
        cmd[4] = i; // 修改界面ID

        bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, cmd, sizeof(cmd)); // 发送数据
    }
}

/**
 * @brief  串口屏上报温度数据
 * @param  [in] temp 温度值
 * @retval None
 * */
void SerialScreen_ReportTemperature(float temp)
{
    char GUI_Showbuf[16]; // GUI显示缓冲区

    // 数据上报到屏幕GUI
    sprintf(GUI_Showbuf, "%.1f", temp);
    uint8_t buf1[] = {0xEE, 0xB1, 0x10, 0x00, 0x01, 0x00, 0x05};
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, buf1, sizeof(buf1)); // 发送数据头
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, (uint8_t *)GUI_Showbuf, strlen(GUI_Showbuf));
    uint8_t buf2[] = {0xFF, 0xFC, 0xFF, 0xFF};
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, buf2, sizeof(buf2)); // 发送数据尾
}

/**
 * @brief  串口屏上报湿度数据
 * @param  [in] Humi 湿度值
 * @retval None
 * */
void SerialScreen_ReportHumidity(float Humi)
{
    char GUI_Showbuf[16]; // GUI显示缓冲区

    // 数据上报到屏幕GUI
    sprintf(GUI_Showbuf, "%.1f", Humi);
    uint8_t buf1[] = {0xEE, 0xB1, 0x10, 0x00, 0x01, 0x00, 0x06};
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, buf1, sizeof(buf1)); // 发送数据头
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, (uint8_t *)GUI_Showbuf, strlen(GUI_Showbuf));
    uint8_t buf2[] = {0xFF, 0xFC, 0xFF, 0xFF};
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, buf2, sizeof(buf2)); // 发送数据尾
}

/**
 * @brief  串口屏上报光照度数据
 * @param  [in] Illum 光照值
 * @retval None
 * */
void SerialScreen_ReportLight(uint16_t Illum)
{
    char GUI_Showbuf[16]; // GUI显示缓冲区

    // 数据上报到屏幕GUI
    sprintf(GUI_Showbuf, "%d", Illum);
    uint8_t buf1[] = {0xEE, 0xB1, 0x10, 0x00, 0x01, 0x00, 0x07};
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, buf1, sizeof(buf1)); // 发送数据头
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, (uint8_t *)GUI_Showbuf, strlen(GUI_Showbuf));
    uint8_t buf2[] = {0xFF, 0xFC, 0xFF, 0xFF};
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, buf2, sizeof(buf2)); // 发送数据尾
}
// strcpy(environment_data[0], cJSON_GetObjectItemCaseSensitive(msg_cjson, "temperature")->valuestring);//温度
// strcpy(environment_data[1], cJSON_GetObjectItemCaseSensitive(msg_cjson, "hum")->valuestring);//湿度
// strcpy(environment_data[2], cJSON_GetObjectItemCaseSensitive(msg_cjson, "illuminance")->valuestring);//光照度
// strcpy(environment_data[3], cJSON_GetObjectItemCaseSensitive(msg_cjson, "water_temp")->valuestring);//水温
// strcpy(environment_data[4], cJSON_GetObjectItemCaseSensitive(msg_cjson, "PH")->valuestring);//PH
// strcpy(environment_data[5], cJSON_GetObjectItemCaseSensitive(msg_cjson, "solubility")->valuestring);//溶解度
// strcpy(environment_data[6], cJSON_GetObjectItemCaseSensitive(msg_cjson, "turbidity")->valuestring);//浑浊度
// strcpy(environment_data[7], cJSON_GetObjectItemCaseSensitive(msg_cjson, "longitude")->valuestring);//经度
// strcpy(environment_data[8], cJSON_GetObjectItemCaseSensitive(msg_cjson, "latitude")->valuestring);//纬度
// strcpy(ship[0], cJSON_GetObjectItemCaseSensitive(msg_cjson, "speed")->valuestring);//速度
// strcpy(ship[1], cJSON_GetObjectItemCaseSensitive(msg_cjson, "angle")->valuestring);//角度
// strcpy(ship[2], cJSON_GetObjectItemCaseSensitive(msg_cjson, "electricity")->valuestring);//电量
// 帧头
const uint8_t FH[][7] = {
    {0xEE, 0xB1, 0x10, 0x00, 0x01, 0x00, 0x05}, // 温度
    {0xEE, 0xB1, 0x10, 0x00, 0x01, 0x00, 0x06}, // 湿度
    {0xEE, 0xB1, 0x10, 0x00, 0x01, 0x00, 0x07}, // 光照度
    {0xEE, 0xB1, 0x10, 0x00, 0x01, 0x00, 0x0d}, // 水温
    {0xEE, 0xB1, 0x10, 0x00, 0x01, 0x00, 0x0a}, // PH
    {0xEE, 0xB1, 0x10, 0x00, 0x01, 0x00, 0x0b}, // 溶解度
    {0xEE, 0xB1, 0x10, 0x00, 0x01, 0x00, 0x0c}, // 浑浊度

    {0xEE, 0xB1, 0x10, 0x00, 0x01, 0x00, 0x0e}, // 经度
    {0xEE, 0xB1, 0x10, 0x00, 0x01, 0x00, 0x0f}, // 纬度

    {0xEE, 0xB1, 0x10, 0x00, 0x01, 0x00, 0x08},  // 速度
    {0xEE, 0xB1, 0x10, 0x00, 0x01, 0x00, 0x09},  // 角度
    {0xEE, 0xB1, 0x23, 0x00, 0x01, 0x00, 0x01},  // 电量
    {0xEE, 0xB1, 0x10, 0x00, 0x02, 0x00, 0x0a},  // 速度2
    {0xEE, 0xB1, 0x10, 0x00, 0x02, 0x00, 0x0b},  // 角度2
    {0xEE, 0xB1, 0x23, 0x00, 0x02, 0x00, 0x01},  // 速度2
    {0xEE, 0xB1, 0x10, 0x00, 0x02, 0x00, 0x0c},  // 经度2
    {0xEE, 0xB1, 0x10, 0x00, 0x02, 0x00, 0x0d}}; // 纬度2

// 帧尾
const uint8_t FR[4] = {0xFF, 0xFC, 0xFF, 0xFF};
void data_report(char data[][15], uint8_t len)
{
    for (uint8_t i = 0; i < len; i++)
    {
        bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FH[i], sizeof(FH[i]));
        bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, (uint8_t *)data[i], strlen(data[i]));
        bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FR, sizeof(FR)); // 发送数据尾
    }

    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FH[15], sizeof(FH[15]));
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, (uint8_t *)data[7], strlen(data[7]));
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FR, sizeof(FR)); // 发送数据尾

    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FH[16], sizeof(FH[16]));
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, (uint8_t *)data[8], strlen(data[8]));
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FR, sizeof(FR)); // 发送数据尾
}
void data_report2(char data[][10], uint8_t len)
{
    int32_t temp1 = atoi(data[1]);      // 角度
    uint8_t temp2 = atoi(data[2]) / 16; // 电量
    uint8_t temp3[4];                   // 角度

    for (uint8_t i = 0; i < 4; i++)
    {
        temp3[3 - i] = temp1 % 0xff;
        temp1 = temp1 >> 8;
    }
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FH[9], sizeof(FH[9]));
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, (uint8_t *)data[0], strlen(data[0])); // 速度
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FR, sizeof(FR));

    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FH[10], sizeof(FH[10]));
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, temp3, 4); // 角度
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FR, sizeof(FR));

    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FH[11], sizeof(FH[11]));
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, &temp2, 1); // 电量
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FR, sizeof(FR));

    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FH[12], sizeof(FH[12]));
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, (uint8_t *)data[0], strlen(data[0])); // 速度2
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FR, sizeof(FR));

    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FH[13], sizeof(FH[13]));
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, temp3, 4); // 角度2
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FR, sizeof(FR));

    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FH[14], sizeof(FH[14]));
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, &temp2, 1); /// 电量2
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FR, sizeof(FR));
}
void network_state(uint8_t state)
{

    uint8_t temp[] = {0xEE, 0xB1, 0x23, 0x00, 0x01, 0x00, 0x02};
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, temp, sizeof(temp));
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, &state, 1); // 4G
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FR, sizeof(FR));
    temp[4] = 0x02; // 界面2
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, temp, sizeof(temp));
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, &state, 1); // 4G
    bsp_uart_send_data(CONFIG_SERIAL_SCREEN_UART_ID, FR, sizeof(FR));
}
